﻿using System;
using System.Collections.Generic;
using System.Data;
using Chappie.Infrastructure.DataStructure;
using Chappie.Infrastructure.Domain;
using Chappie.Infrastructure.Specification;
using ServiceStack.OrmLite;

namespace Chappie.Infrastructure.Repository
{
    public class OrmLiteRepository<TAggregateRoot> : IRepository<TAggregateRoot>
        where TAggregateRoot : class, IAggregateRoot
    {
        private const string conStr = "server ='localhost';userid ='root'; password ='sa'; database = 'test'";

        private readonly OrmLiteConnectionFactory _dbFactory = new OrmLiteConnectionFactory(conStr,
            MySqlDialect.Provider);

        public void Add(TAggregateRoot aggregateRoot)
        {
            throw new NotImplementedException();
        }

        public void Remove(TAggregateRoot aggregateRoot)
        {
            throw new NotImplementedException();
        }

        public void Update(TAggregateRoot aggregateRoot)
        {
            throw new NotImplementedException();
        }

        public TAggregateRoot FindSingleOrDefault(ISpecification<TAggregateRoot> specification)
        {
            using (IDbConnection db = _dbFactory.OpenDbConnection())
            {
                return db.Single(specification.GetExpression());
            }
        }

        public bool Exists(ISpecification<TAggregateRoot> specification)
        {
            using (IDbConnection db = _dbFactory.OpenDbConnection())
            {
                return db.Exists<TAggregateRoot>(specification.GetExpression());
            }
        }

        public IEnumerable<TAggregateRoot> FindAll()
        {
            using (IDbConnection db = _dbFactory.OpenDbConnection())
            {
                return db.Select<TAggregateRoot>();
            }
        }

        public PagedResult<TAggregateRoot> FindAll(int pageNumber, int pageSize)
        {
            using (IDbConnection db = _dbFactory.OpenDbConnection())
            {
                var totalRecords = (int) db.Count<TAggregateRoot>();
                int totalPages = totalRecords/pageSize + 1;
                List<TAggregateRoot> data = db.Select<TAggregateRoot>(m => m.Limit((pageNumber - 1)*pageSize, pageSize));
                var result = new PagedResult<TAggregateRoot>(totalRecords, totalPages, pageSize, pageNumber, data);
                return result;
            }
        }

        public IEnumerable<TAggregateRoot> FindAll(ISpecification<TAggregateRoot> specification)
        {
            using (IDbConnection db = _dbFactory.OpenDbConnection())
            {
                return db.Select(specification.GetExpression());
            }
        }

        public PagedResult<TAggregateRoot> FindAll(ISpecification<TAggregateRoot> specification,
                                                    int pageNumber,
                                                    int pageSize)
        {
            using (IDbConnection db = _dbFactory.OpenDbConnection())
            {
                var totalRecords = (int) db.Count<TAggregateRoot>();
                int totalPages = totalRecords/pageSize + 1;
                List<TAggregateRoot> data =
                    db.Select<TAggregateRoot>(
                        m => m.Limit((pageNumber - 1)*pageSize, pageSize).And(specification.GetExpression()));
                var result = new PagedResult<TAggregateRoot>(totalRecords, totalPages, pageSize, pageNumber, data);
                return result;
            }
        }
    }
}